mod client;
mod config;
mod tool;

use anyhow::{Ok, Result};
use clap::Parser;
use client::McpClient;
use config::ParamConfig;
use rmcp::transport::{SseServer, sse_server::SseServerConfig};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

#[derive(Parser)]
struct Cli {
    /// The path to the config file
    #[arg(default_value="./config.json")]
    config: std::path::PathBuf,
}

#[tokio::main]
async fn main() -> Result<()> {
    let args = Cli::parse();
    // Initialize logging
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| format!("info,{}=debug", env!("CARGO_CRATE_NAME")).into()),
        )
        .with(tracing_subscriber::fmt::layer())
        .init();

    tracing::info!("start");
    let conf = ParamConfig::load(args.config).unwrap();
    let client = McpClient::new(&conf).await.unwrap();
    let tool_set = client.clone_tools().await.unwrap();

    let bind_address = format!("{}:{}", conf.host, conf.port);
    tracing::info!("npx @modelcontextprotocol/inspector");
    tracing::info!("listening on {}", bind_address);
    let config = SseServerConfig {
        bind: bind_address.parse()?,
        sse_path: "/sse".to_string(),
        post_path: "/message".to_string(),
        ct: tokio_util::sync::CancellationToken::new(),
        sse_keep_alive: None,
    };

    let sse_server = SseServer::serve_with_config(config).await.unwrap();
    let ct = sse_server.with_service(move || tool_set.clone());

    tokio::signal::ctrl_c().await?;
    ct.cancel();
    tracing::info!("shutdown");
    Ok(())
}
